/**
 * echarts图表类：树图
 *
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author Loutongbing (娄同兵, loutongbing@126.com)
 */


var ChartBase = require('./base');
var GOLDEN_SECTION = 0.618;
// 图形依赖
var IconShape = require('../util/shape/Icon');
var ImageShape = require('zrender/shape/Image');
var LineShape = require('zrender/shape/Line');
var BezierCurveShape = require('zrender/shape/BezierCurve');
// 布局依赖
var TreeLayout = require('../layout/Tree');
// 数据依赖
var TreeData = require('../data/Tree');
var ecConfig = require('../config');
// 默认参数
ecConfig.tree = {
    zlevel: 1,
    // 一级层叠
    z: 2,
    // 二级层叠
    calculable: false,
    clickable: true,
    rootLocation: {},
    orient: 'vertical',
    symbol: 'circle',
    symbolSize: 20,
    nodePadding: 30,
    layerPadding: 100,
    /*rootLocation: {
            x: 'center' | 'left' | 'right' | 'x%' | {number},
            y: 'center' | 'top' | 'bottom' | 'y%' | {number}
        },*/
    itemStyle: {
        normal: {
            // color: 各异,
            label: { show: true },
            lineStyle: {
                width: 1,
                color: '#777',
                type: 'curve'    // curve
            }
        },
        emphasis: {}
    }
};
var ecData = require('../util/ecData');
var zrConfig = require('zrender/config');
var zrEvent = require('zrender/tool/event');
var zrUtil = require('zrender/tool/util');
/**
     * 构造函数
     * @param {Object} messageCenter echart消息中心
     * @param {ZRender} zr zrender实例
     * @param {Object} series 数据
     * @param {Object} component 组件
     * @constructor
     * @exports Tree
     */
function Tree(ecTheme, messageCenter, zr, option, myChart) {
    // 图表基类
    ChartBase.call(this, ecTheme, messageCenter, zr, option, myChart);
    this.refresh(option);
}
Tree.prototype = {
    type: ecConfig.CHART_TYPE_TREE,
    /**
         * 构建单个
         *
         * @param {Object} data 数据
         */
    _buildShape: function (series, seriesIndex) {
        var data = series.data[0];
        this.tree = TreeData.fromOptionData(data.name, data.children);
        // 添加root的data
        this.tree.root.data = data;
        // 根据root坐标 方向 对每个节点的坐标进行映射
        this._setTreeShape(series);
        // 递归画出树节点与连接线
        this.tree.traverse(function (treeNode) {
            this._buildItem(treeNode, series, seriesIndex);
            // 画连接线
            if (treeNode.children.length > 0) {
                this._buildLink(treeNode, series);
            }
        }, this);
        var panable = series.roam === true || series.roam === 'move';
        var zoomable = series.roam === true || series.roam === 'scale';
        // Enable pan and zooom
        this.zr.modLayer(this.getZlevelBase(), {
            panable: panable,
            zoomable: zoomable
        });
        if (this.query('markPoint.effect.show') || this.query('markLine.effect.show')) {
            this.zr.modLayer(ecConfig.EFFECT_ZLEVEL, {
                panable: panable,
                zoomable: zoomable
            });
        }
        this.addShapeList();
    },
    /**
         * 构建单个item
         */
    _buildItem: function (treeNode, serie, seriesIndex) {
        var queryTarget = [
            treeNode.data,
            serie
        ];
        var symbol = this.deepQuery(queryTarget, 'symbol');
        // 多级控制
        var normal = this.deepMerge(queryTarget, 'itemStyle.normal') || {};
        var emphasis = this.deepMerge(queryTarget, 'itemStyle.emphasis') || {};
        var normalColor = normal.color || this.zr.getColor();
        var emphasisColor = emphasis.color || this.zr.getColor();
        var angle = -treeNode.layout.angle || 0;
        // 根节点不旋转
        if (treeNode.id === this.tree.root.id) {
            angle = 0;
        }
        var textPosition = 'right';
        if (Math.abs(angle) >= Math.PI / 2 && Math.abs(angle) < Math.PI * 3 / 2) {
            angle += Math.PI;
            textPosition = 'left';
        }
        var rotation = [
            angle,
            treeNode.layout.position[0],
            treeNode.layout.position[1]
        ];
        var shape = new IconShape({
            zlevel: this.getZlevelBase(),
            z: this.getZBase() + 1,
            rotation: rotation,
            clickable: this.deepQuery(queryTarget, 'clickable'),
            style: {
                x: treeNode.layout.position[0] - treeNode.layout.width * 0.5,
                y: treeNode.layout.position[1] - treeNode.layout.height * 0.5,
                width: treeNode.layout.width,
                height: treeNode.layout.height,
                iconType: symbol,
                color: normalColor,
                brushType: 'both',
                lineWidth: normal.borderWidth,
                strokeColor: normal.borderColor
            },
            highlightStyle: {
                color: emphasisColor,
                lineWidth: emphasis.borderWidth,
                strokeColor: emphasis.borderColor
            }
        });
        if (shape.style.iconType.match('image')) {
            shape.style.image = shape.style.iconType.replace(new RegExp('^image:\\/\\/'), '');
            shape = new ImageShape({
                rotation: rotation,
                style: shape.style,
                highlightStyle: shape.highlightStyle,
                clickable: shape.clickable,
                zlevel: this.getZlevelBase(),
                z: this.getZBase()
            });
        }
        // 节点标签样式
        if (this.deepQuery(queryTarget, 'itemStyle.normal.label.show')) {
            shape.style.text = treeNode.data.label == null ? treeNode.id : treeNode.data.label;
            shape.style.textPosition = this.deepQuery(queryTarget, 'itemStyle.normal.label.position');
            // 极坐标另外计算 时钟哪个侧面
            if (serie.orient === 'radial' && shape.style.textPosition !== 'inside') {
                shape.style.textPosition = textPosition;
            }
            shape.style.textColor = this.deepQuery(queryTarget, 'itemStyle.normal.label.textStyle.color');
            shape.style.textFont = this.getFont(this.deepQuery(queryTarget, 'itemStyle.normal.label.textStyle') || {});
        }
        if (this.deepQuery(queryTarget, 'itemStyle.emphasis.label.show')) {
            shape.highlightStyle.textPosition = this.deepQuery(queryTarget, 'itemStyle.emphasis.label.position');
            shape.highlightStyle.textColor = this.deepQuery(queryTarget, 'itemStyle.emphasis.label.textStyle.color');
            shape.highlightStyle.textFont = this.getFont(this.deepQuery(queryTarget, 'itemStyle.emphasis.label.textStyle') || {});
        }
        // todo
        ecData.pack(shape, serie, seriesIndex, treeNode.data, 0, treeNode.id);
        this.shapeList.push(shape);
    },
    _buildLink: function (parentNode, serie) {
        var lineStyle = serie.itemStyle.normal.lineStyle;
        // 折线另外计算
        if (lineStyle.type === 'broken') {
            this._buildBrokenLine(parentNode, lineStyle, serie);
            return;
        }
        for (var i = 0; i < parentNode.children.length; i++) {
            var xStart = parentNode.layout.position[0];
            var yStart = parentNode.layout.position[1];
            var xEnd = parentNode.children[i].layout.position[0];
            var yEnd = parentNode.children[i].layout.position[1];
            switch (lineStyle.type) {
            case 'curve':
                this._buildBezierCurve(parentNode, parentNode.children[i], lineStyle, serie);
                break;
            // 折线
            case 'broken':
                break;
            // default画直线
            default:
                var shape = this._getLine(xStart, yStart, xEnd, yEnd, lineStyle);
                this.shapeList.push(shape);
            }
        }
    },
    _buildBrokenLine: function (parentNode, lineStyle, serie) {
        // 引用_getLine需要把type改为solid
        var solidLineStyle = zrUtil.clone(lineStyle);
        solidLineStyle.type = 'solid';
        var shapes = [];
        var xStart = parentNode.layout.position[0];
        var yStart = parentNode.layout.position[1];
        var orient = serie.orient;
        // 子节点的y
        var yEnd = parentNode.children[0].layout.position[1];
        // 中点x y
        var xMiddle = xStart;
        var yMiddle = yStart + (yEnd - yStart) * (1 - GOLDEN_SECTION);
        // 中线的起始
        var xMiddleStart = parentNode.children[0].layout.position[0];
        var yMiddleStart = yMiddle;
        var xMiddleEnd = parentNode.children[parentNode.children.length - 1].layout.position[0];
        var yMiddleEnd = yMiddle;
        // 水平状态
        if (orient === 'horizontal') {
            var xEnd = parentNode.children[0].layout.position[0];
            xMiddle = xStart + (xEnd - xStart) * (1 - GOLDEN_SECTION);
            yMiddle = yStart;
            xMiddleStart = xMiddle;
            yMiddleStart = parentNode.children[0].layout.position[1];
            xMiddleEnd = xMiddle;
            yMiddleEnd = parentNode.children[parentNode.children.length - 1].layout.position[1];
        }
        // 第一条 从根节点垂直向下
        shapes.push(this._getLine(xStart, yStart, xMiddle, yMiddle, solidLineStyle));
        // 第二条 横向
        shapes.push(this._getLine(xMiddleStart, yMiddleStart, xMiddleEnd, yMiddleEnd, solidLineStyle));
        // 第三条 垂直向下到子节点
        for (var i = 0; i < parentNode.children.length; i++) {
            xEnd = parentNode.children[i].layout.position[0];
            yEnd = parentNode.children[i].layout.position[1];
            // 水平状态
            if (orient === 'horizontal') {
                yMiddleStart = yEnd;
            } else {
                xMiddleStart = xEnd;
            }
            shapes.push(this._getLine(xMiddleStart, yMiddleStart, xEnd, yEnd, solidLineStyle));
        }
        this.shapeList = this.shapeList.concat(shapes);
    },
    _getLine: function (xStart, yStart, xEnd, yEnd, lineStyle) {
        if (xStart === xEnd) {
            xStart = xEnd = this.subPixelOptimize(xStart, lineStyle.width);
        }
        if (yStart === yEnd) {
            yStart = yEnd = this.subPixelOptimize(yStart, lineStyle.width);
        }
        return new LineShape({
            zlevel: this.getZlevelBase(),
            hoverable: false,
            style: zrUtil.merge({
                xStart: xStart,
                yStart: yStart,
                xEnd: xEnd,
                yEnd: yEnd,
                lineType: lineStyle.type,
                strokeColor: lineStyle.color,
                lineWidth: lineStyle.width
            }, lineStyle, true)
        });
    },
    _buildBezierCurve: function (parentNode, treeNode, lineStyle, serie) {
        var offsetRatio = GOLDEN_SECTION;
        var orient = serie.orient;
        var xStart = parentNode.layout.position[0];
        var yStart = parentNode.layout.position[1];
        var xEnd = treeNode.layout.position[0];
        var yEnd = treeNode.layout.position[1];
        var cpX1 = xStart;
        var cpY1 = (yEnd - yStart) * offsetRatio + yStart;
        var cpX2 = xEnd;
        var cpY2 = (yEnd - yStart) * (1 - offsetRatio) + yStart;
        if (orient === 'horizontal') {
            cpX1 = (xEnd - xStart) * offsetRatio + xStart;
            cpY1 = yStart;
            cpX2 = (xEnd - xStart) * (1 - offsetRatio) + xStart;
            cpY2 = yEnd;
        } else if (orient === 'radial') {
            // 根节点 画直线
            if (parentNode.id === this.tree.root.id) {
                cpX1 = (xEnd - xStart) * offsetRatio + xStart;
                cpY1 = (yEnd - yStart) * offsetRatio + yStart;
                cpX2 = (xEnd - xStart) * (1 - offsetRatio) + xStart;
                cpY2 = (yEnd - yStart) * (1 - offsetRatio) + yStart;
            } else {
                var xStartOrigin = parentNode.layout.originPosition[0];
                var yStartOrigin = parentNode.layout.originPosition[1];
                var xEndOrigin = treeNode.layout.originPosition[0];
                var yEndOrigin = treeNode.layout.originPosition[1];
                var rootX = this.tree.root.layout.position[0];
                var rootY = this.tree.root.layout.position[1];
                cpX1 = xStartOrigin;
                cpY1 = (yEndOrigin - yStartOrigin) * offsetRatio + yStartOrigin;
                cpX2 = xEndOrigin;
                cpY2 = (yEndOrigin - yStartOrigin) * (1 - offsetRatio) + yStartOrigin;
                var rad = (cpX1 - this.minX) / this.width * Math.PI * 2;
                cpX1 = cpY1 * Math.cos(rad) + rootX;
                cpY1 = cpY1 * Math.sin(rad) + rootY;
                rad = (cpX2 - this.minX) / this.width * Math.PI * 2;
                cpX2 = cpY2 * Math.cos(rad) + rootX;
                cpY2 = cpY2 * Math.sin(rad) + rootY;
            }
        }
        var shape = new BezierCurveShape({
            zlevel: this.getZlevelBase(),
            hoverable: false,
            style: zrUtil.merge({
                xStart: xStart,
                yStart: yStart,
                cpX1: cpX1,
                cpY1: cpY1,
                cpX2: cpX2,
                cpY2: cpY2,
                xEnd: xEnd,
                yEnd: yEnd,
                strokeColor: lineStyle.color,
                lineWidth: lineStyle.width
            }, lineStyle, true)
        });
        this.shapeList.push(shape);
    },
    _setTreeShape: function (serie) {
        // 跑出来树的layout
        var treeLayout = new TreeLayout({
            nodePadding: serie.nodePadding,
            layerPadding: serie.layerPadding
        });
        this.tree.traverse(function (treeNode) {
            var queryTarget = [
                treeNode.data,
                serie
            ];
            var symbolSize = this.deepQuery(queryTarget, 'symbolSize');
            if (typeof symbolSize === 'number') {
                symbolSize = [
                    symbolSize,
                    symbolSize
                ];
            }
            treeNode.layout = {
                width: symbolSize[0],
                // 节点大小
                height: symbolSize[1]
            };
        }, this);
        treeLayout.run(this.tree);
        // 树的方向
        var orient = serie.orient;
        var rootX = serie.rootLocation.x;
        var rootY = serie.rootLocation.y;
        var zrWidth = this.zr.getWidth();
        var zrHeight = this.zr.getHeight();
        if (rootX === 'center') {
            rootX = zrWidth * 0.5;
        } else {
            rootX = this.parsePercent(rootX, zrWidth);
        }
        if (rootY === 'center') {
            rootY = zrHeight * 0.5;
        } else {
            rootY = this.parsePercent(rootY, zrHeight);
        }
        rootY = this.parsePercent(rootY, zrHeight);
        // 水平树
        if (orient === 'horizontal') {
            rootX = isNaN(rootX) ? 10 : rootX;
            rootY = isNaN(rootY) ? zrHeight * 0.5 : rootY;
        }
        // 极坐标
        if (orient === 'radial') {
            rootX = isNaN(rootX) ? zrWidth * 0.5 : rootX;
            rootY = isNaN(rootY) ? zrHeight * 0.5 : rootY;
        }    // 纵向树
        else {
            rootX = isNaN(rootX) ? zrWidth * 0.5 : rootX;
            rootY = isNaN(rootY) ? 10 : rootY;
        }
        // tree layout自动算出来的root的坐标
        var originRootX = this.tree.root.layout.position[0];
        // 若是极坐标,则求最大最小值
        if (orient === 'radial') {
            var minX = Infinity;
            var maxX = 0;
            var maxWidth = 0;
            this.tree.traverse(function (treeNode) {
                maxX = Math.max(maxX, treeNode.layout.position[0]);
                minX = Math.min(minX, treeNode.layout.position[0]);
                maxWidth = Math.max(maxWidth, treeNode.layout.width);
            });
            //  2 * maxWidth 还不大好但至少保证绝不会重叠 todo
            this.width = maxX - minX + 2 * maxWidth;
            this.minX = minX;
        }
        this.tree.traverse(function (treeNode) {
            var x;
            var y;
            if (orient === 'vertical' && serie.direction === 'inverse') {
                x = treeNode.layout.position[0] - originRootX + rootX;
                y = rootY - treeNode.layout.position[1];
            } else if (orient === 'vertical') {
                x = treeNode.layout.position[0] - originRootX + rootX;
                y = treeNode.layout.position[1] + rootY;
            } else if (orient === 'horizontal' && serie.direction === 'inverse') {
                y = treeNode.layout.position[0] - originRootX + rootY;
                x = rootX - treeNode.layout.position[1];
            } else if (orient === 'horizontal') {
                y = treeNode.layout.position[0] - originRootX + rootY;
                x = treeNode.layout.position[1] + rootX;
            }    // 极坐标
            else {
                x = treeNode.layout.position[0];
                y = treeNode.layout.position[1];
                // 记录原始坐标，以后计算贝塞尔曲线的控制点
                treeNode.layout.originPosition = [
                    x,
                    y
                ];
                var r = y;
                var angle = (x - minX) / this.width * Math.PI * 2;
                x = r * Math.cos(angle) + rootX;
                y = r * Math.sin(angle) + rootY;
                treeNode.layout.angle = angle;
            }
            treeNode.layout.position[0] = x;
            treeNode.layout.position[1] = y;
        }, this);
    },
    /*
         * 刷新
         */
    /*        refresh: function (newOption) {
            this.clear();
            if (newOption) {
                this.option = newOption;
                this.series = newOption.series;
            }

            this._buildShape();
        }*/
    refresh: function (newOption) {
        this.clear();
        if (newOption) {
            this.option = newOption;
            this.series = this.option.series;
        }
        // Map storing all trees of series
        var series = this.series;
        var legend = this.component.legend;
        for (var i = 0; i < series.length; i++) {
            if (series[i].type === ecConfig.CHART_TYPE_TREE) {
                series[i] = this.reformOption(series[i]);
                var seriesName = series[i].name || '';
                this.selectedMap[seriesName] = legend ? legend.isSelected(seriesName) : true;
                if (!this.selectedMap[seriesName]) {
                    continue;
                }
                this._buildSeries(series[i], i);
            }
        }
    },
    _buildSeries: function (series, seriesIndex) {
        /*var tree = Tree.fromOptionData('root', series.data);

            this._treesMap[seriesIndex] = tree;*/
        // this._buildTreemap(tree.root, seriesIndex);
        this._buildShape(series, seriesIndex);
    }
};
zrUtil.inherits(Tree, ChartBase);
// 图表注册
require('../chart').define('tree', Tree);
module.exports = Tree || module.exports;;